<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        svg {
            width: 400px;
            height: 400px;
            border: 1px solid black;
        }
    </style>
</head>

<body>
    <canvas id="canvas" width="300" height="300"></canvas>
    <script>
        function draw(percent, sR) {
            if (percent < 0 || percent > 100) {
                return;
            }
            if (sR < Math.PI / 2 || sR >= 3 / 2 * Math.PI) {
                return;
            }

            var canvas = document.querySelector('#canvas'),
                cxt = canvas.getContext('2d'),
                cWidth = canvas.width,
                cHeight = canvas.height,
                baseColor = '#e1e1e1',
                coverColor = '#fe4d43',
                PI = Math.PI,
                sR = sR || 1 / 2 * PI; // 默认圆弧的起始点弧度为π/2

            var finalRadian = sR + ((PI + (PI - sR) * 2) * percent / 100); // 红圈的终点弧度
            var step = (PI + (PI - sR) * 2) / 100; // 一个1%对应的弧度大小
            var text = 0; // 显示的数字

            window.requestAnimationFrame(paint);
            function paint() {
                cxt.clearRect(0, 0, cWidth, cHeight);
                var endRadian = sR + text * step;
                // 画灰色圆弧
                drawCanvas(cWidth / 2, cHeight / 2, 80, sR, sR + (PI + (PI - sR) * 2), baseColor, 2);
                // 画红色圆弧
                drawCanvas(cWidth / 2, cHeight / 2, 80, sR, endRadian, coverColor, 2);

                // 画红色圆头
                // 红色圆头其实就是一个圆，关键的是找到其圆心，涉及到三角函数知识，自己画个图一看就明了
                var angle = 2 * PI - endRadian; // 转换成逆时针方向的弧度（三角函数中的）
                xPos = Math.cos(angle) * 80 + cWidth / 2; // 红色圆 圆心的x坐标
                yPos = -Math.sin(angle) * 80 + cHeight / 2; // 红色圆 圆心的y坐标
                drawCanvas(xPos, yPos, 2, 0, 2 * PI, coverColor, 2);

                // 数字
                cxt.fillStyle = coverColor;
                cxt.font = '40px PT Sans';
                var textWidth = cxt.measureText(text + '%').width;
                cxt.fillText(text + '%', cWidth / 2 - textWidth / 2, cHeight / 2 + 15);
                text++;

                if (endRadian.toFixed(2) < finalRadian.toFixed(2)) {
                    window.requestAnimationFrame(paint);
                }
            }

            function drawCanvas(x, y, r, sRadian, eRadian, color, lineWidth) {
                cxt.beginPath();
                cxt.lineCap = "round";
                cxt.strokeStyle = color;
                cxt.lineWidth = lineWidth;
                cxt.arc(x, y, r, sRadian, eRadian, false);
                cxt.stroke();
            }
        }
        draw(30)
    </script>
    <canvas id="myCanvas" width="400" height="400"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');

        function drawCanvas(centerX, centerY, outerRadius, innerRadius, endRadian, colors, lineWidth) {
            const totalSegments = 3; // 三个颜色段
            const segmentRadian = endRadian / totalSegments;

            for (let i = 0; i < totalSegments; i++) {
                const color = colors[i % colors.length];
                ctx.beginPath();
                ctx.strokeStyle = color;
                ctx.lineWidth = lineWidth;

                // 绘制每个颜色段
                ctx.arc(centerX, centerY, outerRadius, i * segmentRadian, (i + 1) * segmentRadian, false);
                ctx.arc(centerX, centerY, innerRadius, (i + 1) * segmentRadian, i * segmentRadian, true);

                ctx.stroke();
            }
        }

        drawCanvas(canvas.width / 2, canvas.height / 2, 150, 140, 2 * Math.PI, ['red', 'green', 'blue'], 2);
    </script>

    <canvas id="myCanvas1" width="200" height="200" style="border: 0px;"></canvas>
    <script>
        {
            const canvas = document.getElementById('myCanvas1');
            const ctx = canvas.getContext('2d');

            function drawSolidRing(centerX, centerY, outerRadius, innerRadius, endRadian, colors) {
                const totalSegments = 3; // 三个颜色段
                const segmentRadian = endRadian / totalSegments;

                for (let i = 0; i < totalSegments; i++) {
                    const color = colors[i % colors.length];
                    ctx.beginPath();

                    // 绘制每个颜色段
                    ctx.fillStyle = color;
                    ctx.arc(centerX, centerY, outerRadius, i * segmentRadian, (i + 1) * segmentRadian, false);
                    ctx.arc(centerX, centerY, innerRadius, (i + 1) * segmentRadian, i * segmentRadian, true);

                    ctx.fill();
                }
            }

            drawSolidRing(canvas.width / 2, canvas.height / 2, 75, 70, 2 * Math.PI, ['red', 'green', 'blue']);
        }
    </script>

    <canvas id="myCanvas2" width="400" height="400"></canvas>
    <script>
        {
            const canvas = document.getElementById('myCanvas2');
            const ctx = canvas.getContext('2d');

            function drawGradientRing(centerX, centerY, outerRadius, innerRadius, endRadian, colors) {
                const totalSegments = 3; // 三个颜色段
                const segmentRadian = endRadian / totalSegments;
                const gradientWidth = (outerRadius - innerRadius) / totalSegments;

                for (let i = 0; i < totalSegments; i++) {
                    const color = colors[i % colors.length];
                    const gradient = ctx.createRadialGradient(
                        centerX, centerY, outerRadius - gradientWidth * i,
                        centerX, centerY, outerRadius - gradientWidth * (i + 1)
                    );

                    gradient.addColorStop(0, color);
                    gradient.addColorStop(1, color);

                    ctx.beginPath();
                    ctx.fillStyle = gradient;
                    ctx.arc(centerX, centerY, outerRadius, i * segmentRadian, (i + 1) * segmentRadian, false);
                    ctx.arc(centerX, centerY, innerRadius, (i + 1) * segmentRadian, i * segmentRadian, true);

                    ctx.fill();
                }
            }

            drawGradientRing(canvas.width / 2, canvas.height / 2, 150, 140, 2 * Math.PI, ['red', 'green', 'blue']);
        }
    </script>

    <svg viewBox="0 0 400 400">
        <defs>
            <!-- 创建线性渐变 -->
            <linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
                <!-- 添加颜色停止 -->
                <stop offset="0%" stop-color="red" />
                <stop offset="33.33%" stop-color="green" />
                <stop offset="66.67%" stop-color="blue" />
            </linearGradient>
        </defs>
        <!-- 绘制环形 -->
        <path d="M200,200 m0,-150 a150,150 0 1,0 300,0 a150,150 0 1,0 -300,0" fill="url(#gradient)" />
    </svg>
</body>

</html>